﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Input;
using SqlMiM.Common.ViewModel;
using SqlMiM.Common.Commands;
using System.Collections.ObjectModel;
using System.Diagnostics;
using SqlMiM.SqlIndexes.Core;
using System.Windows.Threading;
using System.Collections;
using System.Windows;
using System.Windows.Data;
using SqlMiM.SqlIndexes.ViewModel;
using SqlMiM.Common.Core;
using SqlMiM.Common.Model;
using SqlMiM.SqlIndexes.Model;
using SqlMiM.Common.Framework.Configuration;
using SqlMiM.Common;
using SqlMiM.SqlIndexes.Options;
using MvvmFoundation.Wpf;

namespace SqlMiM.SqlIndexes.MissingIndexes
{
    public class ViewModel : ObservableObject
    {
        private BackgroundWorker bgw;
        private BackgroundWorker bgwGetPotentialIndexse;
        private ObservableCollection<DatabaseView> databases;
        private CollectionViewSource potentialIndexes;
        private ConfigurationObject configurationObject;
        private RelayCommand<SelectType> selectElements;
        private RelayCommand getPotentialIndexesCommand;

        public CollectionViewSource PotentialIndexesView
        {
            get { return potentialIndexes; }
            set
            {
                potentialIndexes = value;
                this.RaisePropertyChanged("PotentialIndexesView");
            }
        }


        public ObservableCollection<DatabaseView> Databases
        {
            get { return databases; }
            set
            {
                databases = value;
                this.RaisePropertyChanged("Databases");
            }
        }


        /// <summary>
        /// 
        /// </summary>
        public ICommand SelectElements
        {
            get
            {
                if (selectElements == null)
                {
                    selectElements = new RelayCommand<SelectType>(param => this.SelectUnselectReverse(param));

                }
                return selectElements;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        public ICommand SelectPotentialIndexesCommand
        {
            get
            {
                if (getPotentialIndexesCommand == null)
                {
                    getPotentialIndexesCommand = new RelayCommand(this.GetPotentialIndexes);

                }
                return getPotentialIndexesCommand;
            }
        }

        private void GetPotentialIndexes()
        {

            ObservableCollection<PotentialIndexView> razCol = this.PotentialIndexesView.Source as ObservableCollection<PotentialIndexView>;
            razCol.Clear();

            bgwGetPotentialIndexse = new BackgroundWorker();
            bgwGetPotentialIndexse.WorkerReportsProgress = true;

            bgwGetPotentialIndexse.DoWork += (sender, args) => 
            { 
                if (this.Databases != null)
                    this.internalGetPotentialIndexes(); 
            };

            bgwGetPotentialIndexse.ProgressChanged += (sender, args) =>
            {
                List<PotentialIndex> lst = args.UserState as List<PotentialIndex>;

                if (lst == null) return;

                ObservableCollection<PotentialIndexView> col = this.PotentialIndexesView.Source as ObservableCollection<PotentialIndexView>;

                foreach (var fi in lst)
                    col.Add(new PotentialIndexView(fi));
            };

            bgwGetPotentialIndexse.RunWorkerCompleted += (sender, args) =>
            {
                //this.Databases = new ObservableCollection<FragmentedDatabaseView>(args.Result as List<FragmentedDatabaseView>);

                //this.PotentialIndexesView.Source = args.Result as List<PotentialIndexInfoView>;
                //this.PotentialIndexesView.GroupDescriptions.Add(new PropertyGroupDescription("Index_database")); 
            };

            bgwGetPotentialIndexse.RunWorkerAsync();

        }

        private void internalGetPotentialIndexes()
        {
            if (this.Databases == null || this.Databases.Count == 0)
                return;

            foreach (var db in this.Databases)
            {
                if (db.IsChecked)
                {
                    var lstFrags = IndexesService.Current.GetPotentialIndexes(db.Database);

                    bgwGetPotentialIndexse.ReportProgress(0, lstFrags);
                }
            }
        }




        private void SelectUnselectReverse(SelectType type)
        {
            if (this.Databases == null || this.Databases.Count == 0)
                return;

            // Select all
            if (type == SelectType.SelectAll)
            {
                foreach (var lv in this.Databases)
                    lv.IsChecked = true;
            }
            // UnSelect all
            else if (type == SelectType.UnselectAll)
            {
                foreach (var lv in this.Databases)
                    lv.IsChecked = false;
            }
            // Reverse
            else if (type == SelectType.ReverseSelection)
            {
                foreach (var lv in this.Databases)
                    lv.IsChecked = !lv.IsChecked;
            }
        }



        public ViewModel()
        {
            this.PotentialIndexesView = new CollectionViewSource();
            this.PotentialIndexesView.Source = new ObservableCollection<PotentialIndexView>();
            this.PotentialIndexesView.GroupDescriptions.Add(new PropertyGroupDescription("PotentialIndex.DatabaseName"));
            this.Databases = new ObservableCollection<DatabaseView>();

            // Get configuration object
            this.configurationObject = Context.Current.Configuration[IndexOptionsPage.NAME];

            Load();
            
        }

        /// <summary>
        /// Load datas
        /// </summary>
        public void Load()
        {

            this.Databases.Clear();
            (this.PotentialIndexesView.Source as ObservableCollection<PotentialIndexView>).Clear();

            bgw = new BackgroundWorker();

            bgw.DoWork += (sender, args) =>
            {
                bool includeSysTables = (bool)this.configurationObject.GetProperty(IndexOptionsPage.GET_SYSTEM_TABLES_PROPERTY, IndexOptionsPage.GET_SYSTEM_TABLES_DEFAULT_VALUE);

                args.Result = DatabasesService.Current.GetDatabases(includeSysTables);
            };

            bgw.RunWorkerCompleted += (sender, args) =>
            {
                var dbs = args.Result as List<Database>;

                if (dbs == null) return;


                foreach (var db in dbs)
                    this.Databases.Add(new DatabaseView(db));

            };

            bgw.RunWorkerAsync();
        }


    }

    public enum SelectType
    {
        SelectAll,
        UnselectAll,
        ReverseSelection,
    }


}
